#include "qlua.h"

QLua::QLua()
{
    QString path = QCoreApplication::applicationDirPath();
    path.append("/luaScripts");
    path.append("/command.lua");
    QFile file(path);

    if(file.exists())
    {
        this->setScriptFileName(path);
    }
}

QLua::~QLua()
{
    if(L != nullptr)
    {
        L = nullptr;
    }

    this->deleteLater();
}

QString QLua::ScriptFileName() const
{
    return m_ScriptFileName;
}

void QLua::setScriptFileName(const QString &ScriptFileName)
{
    m_ScriptFileName = ScriptFileName;
}

/**
 * @brief 获取命令字符串
 * 
 * 该函数通过调用Lua脚本中的GetCommand方法来获取命令字符串。它将三个参数传递给Lua脚本，
 * 并从脚本中获取执行命令的结果。如果Lua方法获取失败或脚本加载失败，将返回相应的错误信息。
 * 
 * @param p 参数1，传递给Lua脚本的第一个参数
 * @param w 参数2，传递给Lua脚本的第二个参数
 * @param n 参数3，传递给Lua脚本的第三个参数
 * @return QString 返回从Lua脚本中获取的命令字符串或错误信息
 */
QString QLua::GetCommand(QString p, QString w, QString n)
{
    // 初始化返回字符串为空
    QString sRet = "";
    // 将参数p、w、n放入QStringList容器中，方便后续遍历
    QStringList args = {p, w, n};
    
    // 创建Lua状态机
    L = luaL_newstate();
    // 开启常用库，以便Lua脚本可以使用它们
    luaL_openlibs(L);

    // 加载脚本，字符串转宽字符，使用toLocal8Bit()，不要用toLatin1()，否则不支持中文路径
    if(luaL_dofile(L, m_ScriptFileName.toLocal8Bit().data()) == LUA_OK)
    {
        // 获取脚本方法
        lua_getglobal(L, "GetCommand");

        // 检查全局表中是否存在GetCommand方法
        if(!lua_isnil(L, -1))
        {
            // 传达参数压栈
            foreach(QString arg, args)
            {
                lua_pushstring(L, arg.toLatin1());
            }

            // 执行方法
            lua_pcall(L, 3, 1, 0);

            // 检查栈顶是否为字符串类型
            if(lua_isstring(L, -1))
            {
                // 获取结果
                sRet = lua_tostring(L, -1);
            }
        }
        else
        {
            // 如果Lua方法获取失败，设置返回值为错误信息
            sRet = "Lua方法获取失败";
        }
    }
    else
    {
        // 如果脚本加载失败，设置返回值为错误信息
        sRet = "脚本加载失败";
    }

    // 清理栈顶
    lua_pop(L, 1);
    // 关闭Lua状态机
    lua_close(L);
    // 指针归零
    L = nullptr;
    // 返回结果字符串
    return sRet;
}

// QLua类的GetCmd方法，用于执行Lua脚本并获取命令
// 参数: QStringList list - 包含参数的列表
// 返回值: QString - 执行Lua脚本后得到的命令字符串
QString QLua::GetCmd(QStringList list)
{
    QString sRet = "";
    //创建Lua状态机
    L = luaL_newstate();
    //开启常用库
    luaL_openlibs(L);

    //加载脚本,字符串转宽字符，使用toLocal8Bit()，不要用toLatin1(),否则不支持中文路径
    if(luaL_dofile(L, m_ScriptFileName.toLocal8Bit().data()) == LUA_OK)
    {
        if(!list.isEmpty())
        {
            lua_newtable(L);      // 创建一个新 table 并压入栈
            for(int i = 1; i <= list.length(); i++)
            {
                lua_pushnumber(L, i);
                lua_pushstring(L, list.at(i - 1).toLatin1().data());
                lua_settable(L, -3);
            }
            //获取脚本方法
            lua_getglobal(L, "GetCmd");
            // 将table内容压栈
            lua_pushvalue(L, -2);
            if(!lua_isnil(L, -1))
            {
                lua_pcall(L, 1, 1, 0);
                if(lua_isstring(L, -1))
                {
                    sRet = lua_tostring(L, -1);
                }
            }
            else
            {
                sRet = "Lua方法获取失败";
            }
        }
        else
        {
            sRet = "列表空内容";
        }
    }
    else
    {
        sRet = "脚本加载失败";
    }

    //清理栈顶
    lua_pop(L, 1);
    //关闭Lua状态机
    lua_close(L);
    //指针归零
    L = nullptr;
    return sRet;
}
